// 版权所有 Epic Games, Inc. 保留所有权利。

#include "GameplayTagStack.h"

#include "UObject/Stack.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(GameplayTagStack)

//////////////////////////////////////////////////////////////////////
// FGameplayTagStack

/**
 * 获取调试字符串
 */
FString FGameplayTagStack::GetDebugString() const
{
	return FString::Printf(TEXT("%sx%d"), *Tag.ToString(), StackCount); // 格式化标签和堆栈数量
}

//////////////////////////////////////////////////////////////////////
// FGameplayTagStackContainer

/**
 * 添加堆栈
 */
void FGameplayTagStackContainer::AddStack(FGameplayTag Tag, int32 StackCount)
{
	if (!Tag.IsValid()) // 检查标签是否有效
	{
		FFrame::KismetExecutionMessage(TEXT("向AddStack传递了无效标签"), ELogVerbosity::Warning); // 输出警告消息
		return;
	}

	if (StackCount > 0) // 检查堆栈数量是否大于0
	{
		for (FGameplayTagStack& Stack : Stacks) // 遍历现有堆栈
		{
			if (Stack.Tag == Tag) // 找到匹配的标签
			{
				const int32 NewCount = Stack.StackCount + StackCount; // 计算新数量
				Stack.StackCount = NewCount; // 更新堆栈数量
				TagToCountMap[Tag] = NewCount; // 更新映射表
				MarkItemDirty(Stack); // 标记为脏以进行复制
				return;
			}
		}

		FGameplayTagStack& NewStack = Stacks.Emplace_GetRef(Tag, StackCount); // 创建新堆栈
		MarkItemDirty(NewStack); // 标记新堆栈为脏
		TagToCountMap.Add(Tag, StackCount); // 添加到映射表
	}
}

/**
 * 移除堆栈
 */
void FGameplayTagStackContainer::RemoveStack(FGameplayTag Tag, int32 StackCount)
{
	if (!Tag.IsValid()) // 检查标签是否有效
	{
		FFrame::KismetExecutionMessage(TEXT("向RemoveStack传递了无效标签"), ELogVerbosity::Warning); // 输出警告消息
		return;
	}

	//@TODO: 如果尝试移除不存在的堆栈或数量较小的堆栈，我们应该报错吗？
	if (StackCount > 0) // 检查堆栈数量是否大于0
	{
		for (auto It = Stacks.CreateIterator(); It; ++It) // 使用迭代器遍历堆栈
		{
			FGameplayTagStack& Stack = *It;
			if (Stack.Tag == Tag) // 找到匹配的标签
			{
				if (Stack.StackCount <= StackCount) // 如果堆栈数量小于等于要移除的数量
				{
					It.RemoveCurrent(); // 移除当前堆栈
					TagToCountMap.Remove(Tag); // 从映射表中移除
					MarkArrayDirty(); // 标记数组为脏
				}
				else
				{
					const int32 NewCount = Stack.StackCount - StackCount; // 计算新数量
					Stack.StackCount = NewCount; // 更新堆栈数量
					TagToCountMap[Tag] = NewCount; // 更新映射表
					MarkItemDirty(Stack); // 标记为脏以进行复制
				}
				return;
			}
		}
	}
}

/**
 * 复制移除前处理
 */
void FGameplayTagStackContainer::PreReplicatedRemove(const TArrayView<int32> RemovedIndices, int32 FinalSize)
{
	for (int32 Index : RemovedIndices) // 遍历被移除的索引
	{
		const FGameplayTag Tag = Stacks[Index].Tag; // 获取标签
		TagToCountMap.Remove(Tag); // 从映射表中移除
	}
}

/**
 * 复制添加后处理
 */
void FGameplayTagStackContainer::PostReplicatedAdd(const TArrayView<int32> AddedIndices, int32 FinalSize)
{
	for (int32 Index : AddedIndices) // 遍历被添加的索引
	{
		const FGameplayTagStack& Stack = Stacks[Index]; // 获取堆栈
		TagToCountMap.Add(Stack.Tag, Stack.StackCount); // 添加到映射表
	}
}

/**
 * 复制更改后处理
 */
void FGameplayTagStackContainer::PostReplicatedChange(const TArrayView<int32> ChangedIndices, int32 FinalSize)
{
	for (int32 Index : ChangedIndices) // 遍历被更改的索引
	{
		const FGameplayTagStack& Stack = Stacks[Index]; // 获取堆栈
		TagToCountMap[Stack.Tag] = Stack.StackCount; // 更新映射表
	}
}